<template>
  <div
    @mouseenter="hovering = true"
    @mouseleave="hovering = false"
    style="width: 100%"
  >
    <el-input v-if="inputDisabled" v-model="message"></el-input>
    <el-popover
      v-else
      ref="popover"
      width="—"
      placement="bottom-start"
      :visible-arrow="true"
      trigger="click"
    >
        <template #reference>
          <el-input v-model="message" readonly>
            <template #suffix>
              <cc-icon
                v-if="hovering"
                style="cursor: pointer;color: #c0c4cc"
                @click.stop="clearInput"
                iconId="018dca412c4ebd53fd1d"
              />
            </template>
          </el-input>
        </template>
        <el-scrollbar
          wrap-class="popover-scrollbar"
          wrap-style="min-height:0px;max-height: 400px;min-width: 300px"
          view-style="height:100%;"
          v-loading="loading"
          element-loading-text="数据加载中..."
          :noresize="false"
        >
          <el-row class="tree-row">
            <el-tree
              style="width: 100%"
              ref="tree"
              node-key="id"
              :data="treeData"
              :props="treeProps"
              :default-expanded-keys="expandedData"
              :check-strictly="true"
              :filter-node-method="filterNode"
              :expand-on-click-node="leafSelect"
              @check="handleClick"
              @node-click="nodeClick"
            ></el-tree>
          </el-row>
        </el-scrollbar>
    </el-popover>
  </div>
</template>

<script setup>
import { ref, watch, onMounted, nextTick } from 'vue';
import { useDisabled } from 'element-plus';
import api from '@/http/api'

const emit = defineEmits(['change'])
const props = defineProps({
  dataFieldId: String,
  leafSelect: {
    type: Boolean,
    default: true,
  },
  typeSelect: {
    type: String,
    default: '',
  },
});
const modelValue = defineModel();

const initializing = ref(false);
const tree = ref();
const popover = ref();
const filterText = ref('');
const message = ref('');
const loading = ref(false);
const selectedData = ref(modelValue.value || '');
const expandedData = ref([]);
const inputDisabled = useDisabled();
const treeData = ref([]);
const treeProps = ref({
  children: 'children',
  isLeaf: 'leaf',
  label: 'text'
});
const hovering = ref(false);

const clearInput = () => {
  changeValue('', '');
};

const changeValue = (id, value) => {
  initializing.value = true;
  modelValue.value = id;
  message.value = value;
  emit('change');
  hidePopover()
  nextTick(() => {
    initializing.value = false;
  });
};

const filterNode = (value, data) => {
  if (!value) return true;
  return data.text.indexOf(value) >= 0;
};

const handleClick = (data) => {
  if (props.typeSelect !== '' && props.typeSelect !== data.type) {
    return;
  }

  if (data) {
    tree.value.setCheckedNodes([data]);
    changeValue(data.id || '', data.text || '');
  } else {
    changeValue('', '');
  }
  hidePopover();
};

const nodeClick = (data, node) => {
  if (data.disabled === true) {
    changeValue('', '');
    return;
  }

  if (props.typeSelect !== '' && props.typeSelect !== data.type) {
    return;
  }

  if (!props.leafSelect || (props.leafSelect && node.isLeaf)) {
    if (data.disabled !== undefined && data.disabled === true) {
      return;
    }

    hidePopover()
    tree.value.setCheckedNodes([data]);

    changeValue(data.id || '', data.text || '');
  } else {
    tree.value.setCheckedNodes([]);
  }
};

const loadTree = async() => {
  const url = '/business/data-field/' + props.dataFieldId + '/tree';
  api.post(url, props.query || {}).then(res => {
    treeData.value = res.data.children || [];
    expandedData.value = [treeData.value && treeData.value[0] && treeData.value[0].id];
    if (modelValue.value) {
      expandedData.value.push(modelValue.value);
    }
    calcValue();
  });
};

const calcValue = () => {
  message.value = '';
  if (treeData.value == null || treeData.value.length <= 0) {
    message.value = selectedData.value;
  } else {
    const list = findData(treeData.value, selectedData.value);
    for (let i = 0; i < list.length; i++) {
      if (i > 0) {
        message.value += ',';
      }
      message.value += list[i].text;
    }
  }
};

const findData = (list, ids) => {
  let results = [];
  if (list === undefined || list == null || ids === undefined || ids == null) {
    return results;
  }

  for (let i = 0; i < list.length; i++) {
    const id = list[i].id + '';
    if (id !== '0' && ids.indexOf(id) >= 0) {
      results.push(list[i]);
    }

    if (list[i].children !== undefined && list[i].children != null) {
      results = results.concat(findData(list[i].children, ids));
    }
  }

  return results;
};

const hidePopover = () => {
  popover.value && popover.value.hide()
};

watch(() => modelValue.value, (newVal) => {
  if (initializing.value) return;

  if (tree.value) {
    tree.value.setCheckedNodes([]);
  }

  selectedData.value = (newVal || '');
  if (selectedData.value.length <= 0) {
    return;
  }

  message.value = '';
  calcValue();
});

watch(() => filterText.value, (newVal) => {
  tree.value.filter(newVal);
});

onMounted(() => {
  loadTree()
});
</script>